ez_DES
题目附件如下:
from Crypto.Cipher import DES
import secrets
import string
flag = 'moectf{???}'
characters = string.ascii_letters + string.digits + string.punctuation
key = 'ezdes'+''.join(secrets.choice(characters) for _ in range(3))
assert key[:5] == 'ezdes'
key = key.encode('utf-8')
l = 8
def encrypt(text, key):
cipher = DES.new(key, DES.MODE_ECB)
padded_text = text + (l - len(text) % l) * chr(len(text))
data = cipher.encrypt(padded_text.encode('utf-8'))
return data
c = encrypt(flag, key)
print('c =', c)
# c = b'\xe6\x8b0\xc8m\t?\x1d\xf6\x99sA>\xce \rN\x83z\xa0\xdc{\xbc\xb8X\xb2\xe2q\xa4"\xfc\x07'
作为密码赛道唯二50pts题目之一,此题用意在于让大家初步接触对称密码。
如果你已经了解过基础的DES等对称密码,可以直奔 part2 看解题代码。考虑到新生看的资料可能都是公钥密码范畴的,所以我在下面写几段介绍方便大家入门。
Part 1 对称密码基础
我们可以把密码算法分为两大类,一类是对称加密,另一类是非对称加密,它们的区别在于所使用的密钥是否是对称的。
假如 Alice 想要给 Bob 发消息,为了避免消息被窃取,他们有两种加密方案可以选择。
- 第一种选择:双方共享同一个密钥
,Alice 使用这个共同的密钥对明文 进行加密 ,Bob 可以使用这个密钥进行解密 ,而敌手没有这个密钥的话就无法破解。由于加密和解密使用的密钥是相同的(或者是可以轻松相互转换的),换句话说也就是对称的,所以我们称这种加密方式为对称加密; - 第二种选择:双方不共享密钥,而是分别有一对公钥和私钥
,公钥是散布到公共信道上任何人都可以获取的,而私钥是只有自己才知道的。Alice, Bob,敌手互相都能知道彼此的公钥,但不知道彼此的私钥。Alice 使用 Bob 的公钥对明文 进行加密 ,Bob 必须使用自己的私钥才能进行解密 。由于加密使用的密钥 和解密使用的密钥 不同(或者说是难以由其中一个推导出另一个),所以我们称这种加密方式为非对称加密,也叫公钥加密。
从中我们可以看出,对称加密和非对称加密各有所长,虽然当今时代非对称加密更主流一些(因为它相对来说更节约资源,且和互联网的传播更适配),但这也并不意味着对称加密就失去了价值。比如说,十几轮的置换和异或当然要比非对称加密里那些计算大整数的多少次方快很多。
对称加密里有两大门类:流密码和分组密码。顾名思义,流密码(stream cipher)就像水流一样,从明文串开始横着往后流到密文串,分组密码(block cipher)就是对明文进行分块处理,再从前往后对每一块进行加密。这两者并不是互相冲突的概念,甚至可以相辅相成,例如祖冲之密码就是运用了分组密码思想的流密码。
本次赛题中,只有“杂交随机数”一题涉及到一点流密码,本题“ez_DES”以及“ez_AES”、“(半)^3部电台”这三题需要用到分组密码知识。
Part 2 题解
题目已经将密钥的前5位给出了,只需要遍历最后3位进行解密,而且解密也不需要自己另写函数
有同学可能要问了:直接暴力就完了?这么无脑?
对此我只能表示:毕竟暴力是密码学不可不品的一环
而且很多实际情况下确实只需要掌握调用函数的能力就足够了(
在进行分组加密前需要对明文进行填充,这里的填充方式是自定义的,不过对于解密来说无所谓,反正右大括号后面的对内容无影响
解题代码如下:
from Crypto.Cipher import DES
import string
import itertools
characters = string.ascii_letters + string.digits + string.punctuation
l = 8
c = b'\xe6\x8b0\xc8m\t?\x1d\xf6\x99sA>\xce \rN\x83z\xa0\xdc{\xbc\xb8X\xb2\xe2q\xa4"\xfc\x07'
def encrypt(text, key):
cipher = DES.new(key, DES.MODE_ECB)
padded_text = text+(l-len(text)%l)*chr(len(text))
data = cipher.encrypt(padded_text.encode('utf-8'))
return data
def decrypt(data):
d = data[:8]
for keyy in itertools.product(characters, repeat=3):
print(keyy)
key2 = b'ezdes'+(''.join(keyy)).encode('utf-8')
for ch in characters:
r = encrypt('moectf{'+ch, key2)
if r[:8] == d:
print('key =',key2)
return key2
print('None!')
key = decrypt(c)
cipher = DES.new(key, DES.MODE_ECB)
flag = cipher.decrypt(c)
print(flag)
# key = ezdes8br
# flag = 'moectf{_Ju5t envmEra+e.!}'